package com.ophelisis.common.crypt;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class AESCipher 
{
	private Log log = LogFactory.getLog(this.getClass());
	private int encryptionMode;
	public static final int AES_MODE_CBC = 0;
	public static final int AES_MODE_ECB = 1;

	public static final String AES_NO_PADDING = "NoPadding";
	public static final String AES_ZExRO_PADDING = "ZeroPadding";
	public static final String AES_PKCS7_PADDING = "PKCS5Padding";
	private Cipher aes = null;
	private SecretKeySpec key = null;
	private IvParameterSpec initalVector = null;


	public AESCipher(String key, String initialVector, String paddingMode) throws Exception
	{
		if (StringUtils.isEmpty(key) || StringUtils.isEmpty(initialVector))
			throw new Exception("키와 IV 값을 확인하세요.");
		
		if (encryptionMode == AES_MODE_ECB) 
			this.aes = Cipher.getInstance("AES/ECB/" + paddingMode);
		else
			this.aes = Cipher.getInstance("AES/CBC/" + paddingMode);
		
		this.key = new SecretKeySpec(this.hex2Bytes(key), "AES");
		this.initalVector = new IvParameterSpec(this.hex2Bytes(initialVector));
	}
	
	public String encrypt(byte[] content) {
		byte[] cipherText = null;
		String encrypt = null;
		
		try {
			if (content == null)
				return encrypt;
			if (encryptionMode == AES_MODE_ECB)
				aes.init(Cipher.ENCRYPT_MODE, this.key);
			else
				aes.init(Cipher.ENCRYPT_MODE, this.key, this.initalVector);
			cipherText = aes.doFinal(content);
			encrypt = new String(Base64.encodeBase64(cipherText));
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e);
		}
		return encrypt;

	}

	public String decrypt(byte[] content) 
	{
		byte[] plainText = null;
		String decrypt = null;
		
		try {
			if (content == null)
				return decrypt;
			if (encryptionMode == AES_MODE_ECB) {
				aes.init(Cipher.DECRYPT_MODE, this.key);
			} else {
				aes.init(Cipher.DECRYPT_MODE, this.key, this.initalVector);
			}
			plainText = aes.doFinal(Base64.decodeBase64(content));
			decrypt = new String(plainText, "UTF8");
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e);
		}
		return decrypt;
	}

	private byte[] hex2Bytes(String hex) {
		byte[] b = null;
		int len = 0;
		try {
			len = hex.length();
			if (len % 2 == 1)
				return null;

			b = new byte[len / 2];
			for (int i = 0; i < len; i += 2) {
				b[i >> 1] = (byte) Integer.parseInt(hex.substring(i, i + 2), 16);
			}
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e);
		}
		return b;
	}

	public String sendReform(String str) {
		String result = str;
		result = StringUtils.replace(result, "+", "=VmFfJtM");
		return result;
	}

	public String arrivalReform(String str) {
		String result = str;
		result = StringUtils.replace(result, "=VmFfJtM", "+");
		return result;
	}

	public void setEncryptionMode(int encryptionMode)
	{
		this.encryptionMode = encryptionMode;
	}

	public int getEncryptionMode()
	{
		return encryptionMode;
	}
		
	public static void main(String[] args) throws Exception
	{
		AESCipher aes = null;
		try {
			aes = new AESCipher("1ae49a1a1eb120723f07f1260b145526", "2811da22377d62fcfdb02f29aad77d9e", AESCipher.AES_PKCS7_PADDING);
			aes.setEncryptionMode(AESCipher.AES_MODE_CBC);
			String encode = aes.encrypt("11111111111111111111111111111".getBytes());
			System.out.println(encode);
			String plain = aes.decrypt(encode.getBytes());
			System.out.println(plain);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
